﻿using System.Linq;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Runtime.Serialization;
using NthDownload.BL.Exceptions;
using System.ComponentModel.Composition;
using NthDownload.Contracts.Plugins.BandwidthProviders;

namespace NthDownload.BL
{
    [PartCreationPolicy(CreationPolicy.Shared)]
    [Export(typeof(NthProfile))]
    public class NthProfile : INotifyPropertyChanged
    {
        #region INotifyPropertyChanged

        public event PropertyChangedEventHandler PropertyChanged;

        protected void OnPropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged.Invoke(this, new PropertyChangedEventArgs(propertyName));
            }
        }

        #endregion INotifyPropertyChanged

        #region Class Members

        private ObservableCollection<NthQueue> _queues;
        private ObservableCollection<IBandwidthProvider> _bandwidthProviders;

        #endregion Class Members

        #region Constructor

        public NthProfile()
        {
            //
            // Set Defaults
            //
            Queues = new ObservableCollection<NthQueue>();
            BandwidthProviders = new ObservableCollection<IBandwidthProvider>();
        }

        #endregion Constructor

        #region Properties

        /// <summary>
        /// The queues contained in the profile
        /// </summary>
        public ObservableCollection<NthQueue> Queues
        {
            get
            {
                return _queues;
            }
            set
            {
                _queues = value;
                OnPropertyChanged("Queues");
            }
        }

        /// <summary>
        /// The bandwidth providers in the profile
        /// </summary>
        public ObservableCollection<IBandwidthProvider> BandwidthProviders
        {
            get
            {
                return _bandwidthProviders;
            }
            set
            {
                _bandwidthProviders = value;
                OnPropertyChanged("BandwidthProviders");
            }
        }

        #endregion Properties

        #region Methods

        /// <summary>
        /// Adds a queue to the profile
        /// </summary>
        public void AddQueue(NthQueue queue)
        {
            Queues.Add(queue);
        }

        /// <summary>
        /// Removes a queue form the profile
        /// </summary>
        /// <param name="queue">The queue to remove.</param>
        public void RemoveQueue(NthQueue queue)
        {
            RemoveQueue(queue.GUID);
        }

        /// <summary>
        /// Removes a queue form the profile
        /// </summary>
        /// <param name="guid">GUID of the queue to remove.</param>
        public void RemoveQueue(string guid)
        {
            //
            // Check if queue exists
            //
            NthQueue queue = Queues.FirstOrDefault(q => q.GUID == guid);

            if (queue == null)
            {
                throw new NthQueueNotFoundException("Queue not found in profile.");
            }

            //
            // Check if there are any running downloads in the queue
            //
            if (queue.HasRunningDownloads)
            {
                throw new NthQueueBusyException("Can't remove queue because it contains downloads which are running.");
            }

            //
            // Remove queue
            //
            Queues.Remove(queue);
        }

        /// <summary>
        /// Adds a BandwidthProvider to the profile
        /// </summary>
        public void AddBandwidthProvider(IBandwidthProvider bandwidthProvider)
        {
            BandwidthProviders.Add(bandwidthProvider);
        }

        /// <summary>
        /// Removes a BandwidthProvider form the profile
        /// </summary>
        /// <param name="bandwidthProvider">The BandwidthProvider to remove.</param>
        public void RemoveBandwidthProvider(IBandwidthProvider bandwidthProvider)
        {
            RemoveBandwidthProvider(bandwidthProvider.GUID);
        }

        /// <summary>
        /// Removes a BandwidthProvider form the profile
        /// </summary>
        /// <param name="guid">GUID of the BandwidthProvider to remove.</param>
        public void RemoveBandwidthProvider(string guid)
        {
            //
            // Check if BandwidthProvider exists
            //
            IBandwidthProvider bandwidthProvider = BandwidthProviders.FirstOrDefault(q => q.GUID == guid);

            if (bandwidthProvider == null)
            {
                throw new BandwidthProviderNotFoundException("Bandwidth provider not found in profile.");
            }

            //
            // If any of the queues are using the the bandwidth provider clear it form them
            //
            foreach (NthQueue queue in Queues)
            {
                if (queue.BandwidthProvider != null && queue.BandwidthProvider.GUID == guid)
                {
                    queue.BandwidthProvider = null;
                }
            }

            //
            // Remove BandwidthProvider
            //
            BandwidthProviders.Remove(bandwidthProvider);
        }

        #endregion Methods
    }
}
